package net.apexes.fqueue;

import java.io.IOException;
import java.io.Serializable;
import java.util.AbstractQueue;
import java.util.Iterator;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import net.apexes.fqueue.exception.FileFormatException;

/**
 * 基于文件系统的持久化队列
 * 
 * @author <a href=mailto:hedyn@foxmail.com>HeDYn</a>
 * @author sunli
 */
public class FQueue extends AbstractQueue<byte[]> implements Serializable {
	private static final long serialVersionUID = -1L;

	private FSQueue fsQueue = null;
	private Lock lock = new ReentrantReadWriteLock().writeLock();
	
	public FQueue(String path) throws IOException, FileFormatException {
	    this(path, 1024 * 1024 * 2);
	}

	/**
	 * 创建一个持久化队列
	 * @param path 文件的存储路径
	 * @param entityLimitLength 存储数据的单个文件的大小
	 * @throws IOException
	 * @throws FileFormatException
	 */
	public FQueue(String path, int entityLimitLength) throws IOException, FileFormatException {
		fsQueue = new FSQueue(path, entityLimitLength);
	}

	@Override
	public Iterator<byte[]> iterator() {
		throw new UnsupportedOperationException("iterator Unsupported now");
	}

	@Override
	public int size() {
		return fsQueue.getQueueSize();
	}

	@Override
	public boolean offer(byte[] e) {
		try {
			lock.lock();
			fsQueue.add(e);
			return true;
		} catch (IOException ex) {
		    throw new RuntimeException(ex);
		} catch (FileFormatException ex) {
		} finally {
			lock.unlock();
		}
		return false;
	}

	@Override
	public byte[] peek() {
        try {
			lock.lock();
			return fsQueue.readNext();
		} catch (IOException ex) {
			return null;
		} catch (FileFormatException ex) {
			return null;
		} finally {
			lock.unlock();
		}
	}

	@Override
	public byte[] poll() {
		try {
			lock.lock();
			return fsQueue.readNextAndRemove();
		} catch (IOException ex) {
			return null;
		} catch (FileFormatException ex) {
			return null;
		} finally {
			lock.unlock();
		}
	}
	
	@Override
    public void clear() {
	    try {
            lock.lock();
            fsQueue.clear();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        } catch (FileFormatException e) {
        } finally {
            lock.unlock();
        }
    }

    /**
	 * 关闭文件队列
	 * @throws IOException
	 * @throws FileFormatException
	 */
	public void close() throws IOException, FileFormatException {
		if (fsQueue != null) {
		    fsQueue.close();
		}
	}
}
